package Ruleta;

import java.io.Serializable;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.swing.text.html.HTML;

import org.uqbar.commons.model.ObservableObject;
import org.uqbar.commons.model.UserException;

import apuesta.Apuesta;
import apuesta.TipoApuesta;

import jugador.Jugador;
import jugador.Persona;

public class Mesa extends ObservableObject implements Serializable{

	private static final String JUGADORES = "jugadores";
	private static final String APUESTAS = "apuestasActuales";
	public static final String JUGADORACTUAL = "jugadorActual";

	private Jugador jugadorActual;
	private int numeroActual;
	private static Set numeros = new HashSet(37);
	private Ruleta ruleta = new Ruleta();
	private LinkedList<Jugador> jugadores = new LinkedList<Jugador>();
	private int fichasTotales;
	private List<Apuesta> apuestasActuales = new LinkedList<Apuesta>();
	private List<Apuesta> apuestasTotales = new LinkedList<Apuesta>();
	private boolean yaGiro;
	private int cantidadDeJugadoresPermitidos = 2;
	private int cantidadDeJugadoresActualmente = 0;

	/* CONSTRUCTORES */

	public Mesa(int i) {
		this.setJugadores(jugadores);
		this.fichasTotales = i;
	}

	/* GETTERS AND SETTERS */

	public Mesa() {

	}

	public int getNumeroActual() {
		return numeroActual;
	}

	public void setNumeroActual(int numeroActual) {
		this.numeroActual = numeroActual;
	}

	public static Set getNumeros() {
		return numeros;
	}

	public static void setNumeros(Set numeros) {
		Mesa.numeros = numeros;
	}

	public List<Apuesta> getApuestasTotales() {
		return apuestasTotales;
	}

	public void setApuestasTotales(List<Apuesta> apuestasTotales) {
		this.apuestasTotales = apuestasTotales;
	}

	public Ruleta getRuleta() {
		return ruleta;
	}

	public void setRuleta(Ruleta ruleta) {
		this.ruleta = ruleta;
	}

	public int getFichasTotales() {
		return fichasTotales;
	}

	public void setFichasTotales(int fichasTotales) {
		this.fichasTotales = fichasTotales;
	}

	public List<Apuesta> getApuestasActuales() {
		return apuestasActuales;
	}

	public void setApuestasActuales(List<Apuesta> apuestasActuales) {
		this.apuestasActuales = apuestasActuales;
	}

	public void setJugadores(LinkedList<Jugador> jugadores) {
		this.jugadores = jugadores;
	}

	public LinkedList<Jugador> getJugadores() {
		return jugadores;
	}

	/* METODOS */

	public void registrarJugador(String nombre, int cant) {

		Persona pers = new Persona(nombre, cant);
		Jugador jug = new Jugador(pers);
		this.agregarJugador(jug);

	}

	public void agregarJugador(Jugador j) {
		
			this.jugadores.add(j);
			this.cantidadDeJugadoresActualmente += 1;
			System.out.println("Se agrego a " + j.getNombre()
					+ " correctamente");
		
	}

	public boolean hayLugarDisponible() {
		return this.cantidadDeJugadoresPermitidos > this.cantidadDeJugadoresActualmente;
	}

	public int girar() {
		int numeroGanador = this.ruleta.girar();
		this.yaGiro = true;
		this.numeroActual=numeroGanador;

		return numeroGanador;

	}

	public void chequearApuestasGanadoras() {

		List<Apuesta> ganadores = new LinkedList<Apuesta>();
		List<Apuesta> perdedores = new LinkedList<Apuesta>();
		for (Apuesta a : this.apuestasActuales) {

			if (a.buscarGanadores(this.numeroActual)) {

				ganadores.add(a);
			} else {
				perdedores.add(a);
			}
		}
		this.pagarApuesta(ganadores);
		this.recolectarDinero(perdedores);
		this.limpiarMesa();
		System.out.println("Las apuestas fueron pagadas correctamente");
	}

	public void chequearApuestasGanadoras(int numero) {

		List<Apuesta> ganadores = new LinkedList<Apuesta>();
		List<Apuesta> perdedores = new LinkedList<Apuesta>();
		for (Apuesta a : this.apuestasActuales) {

			if (a.buscarGanadores(numero)) {

				ganadores.add(a);
			} else {
				perdedores.add(a);
			}
		}
		this.pagarApuesta(ganadores);
		this.recolectarDinero(perdedores);
		this.limpiarMesa();
		System.out.println("Las apuestas fueron pagadas con éxito");
	}

	private void limpiarMesa() {

		this.apuestasTotales.addAll(apuestasActuales);
		this.apuestasActuales.clear();
		this.yaGiro = false;
	}

	private void recolectarDinero(List<Apuesta> perdedores) {

		for (Apuesta a : perdedores) {

			setFichasTotales(getFichasTotales() + a.getCantidad());
		}
	}

	public void pagarApuesta(List<Apuesta> ganadores) {

		for (Apuesta apuesta : ganadores) {
			int aPagar = apuesta.cuantoPagas();
			apuesta.getApostador().cobra(aPagar + apuesta.getCantidad());
			this.setFichasTotales(this.getFichasTotales() - aPagar);
		}

	}

	public Jugador obtenerJugador(int nro) {

		return this.jugadores.get(nro);

	}

	public void apostar(Jugador j, TipoApuesta tipo, int nro, int cantFichas) {

		if (cantFichas <= j.getFichas()) {
			Apuesta actual = new Apuesta(j, tipo, nro, cantFichas);
			this.apuestasActuales.add(actual);
			j.setFichas(j.getFichas() - cantFichas);

			//
			this.firePropertyChange(APUESTAS, null, this.apuestasActuales);
		} else {
			System.out.println("No te da la tarasca");
		}

	}

	public List<Apuesta> obtenerApuestasDe(Jugador j) {

		List<Apuesta> resultado = new LinkedList<Apuesta>();
		for (Apuesta a : this.apuestasActuales) {

			if (a.getApostador().equals(j)) {

				resultado.add(a);

			}

		}

		return resultado;

	}

	public int cantidadDeJugadores() {

		return this.jugadores.size();
	}

	public void noVaMas() {

		int resultado = this.girar();
		System.out.println(resultado);

	}

	public void unirse(Persona unaPersona) {

		Jugador player = new Jugador(unaPersona);
		this.agregarJugador(player);
		this.firePropertyChange(JUGADORES, null, player);

	}

	public void retirarse(Jugador jugador) {

		this.jugadores.remove(jugador);

	}

	public Jugador getJugadorCambiado(Jugador unJugador) {

		for (Jugador j : this.jugadores) {

			if (j.equals(unJugador)) {

				return j;

			}

		}

		return unJugador;

	}

	public boolean isPuedeGirar() {

		return !this.apuestasActuales.isEmpty() && !this.yaGiro;
	}

	public boolean isDeboPagar() {
		return this.yaGiro;

	}

	public void setJugadorActual(Jugador jugadorActual) {
		this.jugadorActual = jugadorActual;
	}

	public Jugador getJugadorActual() {
		return jugadorActual;
	}

	public Jugador getJugador() {
		// TODO Auto-generated method stub
		return jugadores.get(0);
	}

	public boolean isYaGiro() {
		return yaGiro;
	}

	public boolean getYaGiro() {
		return yaGiro;
	}
	
	public void setYaGiro(boolean yaGiro) {
		this.yaGiro = yaGiro;
	}

}
